﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Event;
using YooAsset;
using HybridCLR;
using Newtonsoft.Json;
using System.Reflection;
//using FairyGUI;

public class Init : MonoBehaviour
{
    /// <summary>
    /// 资源系统运行模式
    /// </summary>
    public EPlayMode PlayMode = EPlayMode.EditorSimulateMode;

    Assembly HotUpdate;
    //SpriteAtlas atles;
    //public UnityEngine.UI.Image Img;
    //public VideoPlayer videoPlayer;

    void Awake()
    {
        Debug.Log($"资源系统运行模式：{PlayMode}");
        Application.targetFrameRate = 60;
        Application.runInBackground = true;
        DontDestroyOnLoad(this.gameObject);
    }
    IEnumerator Start()
    {
        // 游戏管理器
        GameManager.Instance.Behaviour = this;

        // 初始化事件系统
        UniEvent.Initalize();

        // 初始化资源系统
        YooAssets.Initialize();

        // 加载更新页面
        var go = Resources.Load<GameObject>("PatchWindow");
        GameObject.Instantiate(go);

        // 开始默认资源包补丁更新流程   这里 热更新资源
        var operation = new PatchOperation("AssetsPackage", PlayMode);
        YooAssets.StartOperation(operation);
        yield return operation;

        // 开始原始资源包补丁更新流程  这里 热更新代码
        var operation1 = new PatchOperation("RawPackage", PlayMode);
        YooAssets.StartOperation(operation1);
        yield return operation1;

        // 设置默认的资源包
        var gamePackage = YooAssets.GetPackage("AssetsPackage");
        YooAssets.SetDefaultPackage(gamePackage);

        //开启加载代码  热更新 流程   
        yield return LoadMetadataForAOTAssemblies();
        yield return LoadHotUpdateAssemblies();

        //通过反射直接获取HotUpdate程序集内脚本调用Run方法
        //Type type = HotUpdate.GetType("Hello");
        //type.GetMethod("Run").Invoke(null, null);

        var package = YooAssets.GetPackage("AssetsPackage");
        var loadHandle = package.LoadAssetAsync<GameObject>("launcher");
        yield return loadHandle;
        if (loadHandle.Status == EOperationStatus.Succeed)
        {
            var instantiateHandle = loadHandle.InstantiateAsync();
            yield return instantiateHandle;
            var obj = instantiateHandle.Result;
            GameObject.DontDestroyOnLoad(obj);
            Debug.Log("加载热更新预制体完成");
        }
        package.UnloadUnusedAssetsAsync();


       
    }

   


    private IEnumerator LoadHotUpdateAssemblies()
    {
        var package = YooAssets.TryGetPackage("RawPackage");
        if (package == null)
        {
            Debug.Log("包获取失败");
        }
        var handle = package.LoadRawFileAsync("HotUpdateDLLList");
        yield return handle;
        var data = handle.GetRawFileText();
        var dllNames = JsonConvert.DeserializeObject<List<string>>(data);
        foreach (var DllName in dllNames)
        {
            var dataHandle = package.LoadRawFileAsync(DllName);
            yield return dataHandle;
            if (dataHandle.Status != EOperationStatus.Succeed)
            {
                Debug.Log("资源加载失败" + DllName);
                yield break;
            }
            var dllData = dataHandle.GetRawFileData();
            if (dllData == null)
            {
                Debug.Log("获取Dll数据失败");
                yield break;
            }
            Assembly assembly = Assembly.Load(dllData);
            HotUpdate = assembly;
            Debug.Log($"加载热更新Dll:{DllName}");
        }
    }
    private IEnumerator LoadMetadataForAOTAssemblies()
    {
        HomologousImageMode mode = HomologousImageMode.SuperSet;
        var package = YooAssets.TryGetPackage("RawPackage");
        if (package == null)
        {
            Debug.Log("包获取失败");
        }
        var handle = package.LoadRawFileAsync("AOTDLLList");
        yield return handle;
        var data = handle.GetRawFileText();
        Debug.Log(data);
        var dllNames = JsonConvert.DeserializeObject<List<string>>(data);

        foreach (var name in dllNames)
        {
            var dataHandle = package.LoadRawFileAsync(name);
            yield return dataHandle;
            var dllData = dataHandle.GetRawFileData();
            if (data == null)
            {
                continue;
            }
            // 加载assembly对应的dll，会自动为它hook。一旦aot泛型函数的native函数不存在，用解释器版本代码
            LoadImageErrorCode err = RuntimeApi.LoadMetadataForAOTAssembly(dllData, mode);
            Debug.Log($"LoadMetadataForAOTAssembly:{name}. mode:{mode} ret:{err}");
        }
    }

    private IEnumerator LoadHotUpdateAssemblies1()
    {
        var package = YooAssets.TryGetPackage("AssetsPackage");
        if (package == null)
        {
            Debug.Log("包获取失败");
        }

        var dataHandle = package.LoadAssetAsync<TextAsset>("HotUpdate.dll");
        yield return dataHandle;
        if (dataHandle.Status != EOperationStatus.Succeed)
        {
            Debug.Log("资源加载失败" + "HotUpdate.dll");
            yield break;
        }
        var dllData = dataHandle.AssetObject as TextAsset;
        if (dllData == null)
        {
            Debug.Log("获取Dll数据失败");
            yield break;
        }
        Assembly assembly = Assembly.Load(dllData.bytes);
        HotUpdate = assembly;
        Debug.Log($"加载热更新Dll:{"HotUpdate.dll"}");
    }
    private IEnumerator LoadMetadataForAOTAssemblies1()
    {
        HomologousImageMode mode = HomologousImageMode.SuperSet;
        var package = YooAssets.TryGetPackage("AssetsPackage");
        if (package == null)
        {
            Debug.Log("包获取失败");
        }
      
        var dllNames = new List<string>() { "mscorlib.dll", "System.Core.dll", "System.dll", "System.Runtime.dll", "UniTask.dll" };

        foreach (var name in dllNames)
        {
            var dataHandle = package.LoadRawFileAsync(name);
            yield return dataHandle;
            var dllData = dataHandle.GetRawFileData();
            // 加载assembly对应的dll，会自动为它hook。一旦aot泛型函数的native函数不存在，用解释器版本代码
            LoadImageErrorCode err = RuntimeApi.LoadMetadataForAOTAssembly(dllData, mode);
            Debug.Log($"LoadMetadataForAOTAssembly:{name}. mode:{mode} ret:{err}");
        }
    }


    //private void Update()
    //{
    //    if(Input.GetKeyDown(KeyCode.G))
    //    {
    //        Img.sprite = atles.GetSprite(string.Format("icon_{0}", UnityEngine.Random.Range(0, atles.spriteCount)));
    //    }
    //}
}